import React, { useEffect, useMemo, useRef, useState } from "react";
import Markdown from 'react-markdown';
import rehypeHighlight from 'rehype-highlight'
import remarkGFM from 'remark-gfm';
import { basicSetup, EditorView } from "codemirror";
import { markdown } from "@codemirror/lang-markdown";
import { languages } from "@codemirror/language-data"
import { history } from '@codemirror/commands';
import { api_upload, apis } from "../../../apis";
import { Badge, Button, Col, message, Modal, Row, Spin, Splitter, Tooltip, Upload } from "antd";
import { FileImageOutlined, FileOutlined, FullscreenExitOutlined, FullscreenOutlined, InfoCircleOutlined, RedoOutlined, SaveOutlined, UndoOutlined } from "@ant-design/icons";
import { getText, insertText, redo, setText, undo } from "./options";
import { CustomCode, CustomImage, CustomLink } from './components'
import MarkdownDoc from "./components/MarkdownDoc.md";
import { formatDoc } from "../../../../serve/common";
import { UserAppDetail, UserAppTree } from "../../../../serve/interface";

export interface EditorMarkdownProps {
    app_id: number;
    item: UserAppTree;
    onUpdateTree: (detail: UserAppDetail) => void;
}

export const EditorMarkdown: React.FC<EditorMarkdownProps> = (props) => {
    const { app_id, item, onUpdateTree } = props;
    const [fullScreen, setFullScreen] = useState(false);
    useEffect(() => {
        document.documentElement.addEventListener("fullscreenchange", () => {
            setFullScreen(document.fullscreenElement !== null);
        });
    }, []);
    const [base, setBase] = useState("");
    const [content, setContent] = useState("");
    const [loading, setLoading] = useState(false);
    const [saving, setSaving] = useState(false);
    const loadContent = async function () {
        if (app_id && item) {
            setLoading(true);
            const res = await apis.get_doc({ app_id, item_id: item.id, parent_id: item.parentId })
            if (res.success) {
                setBase(res.data.content)
                setContent(res.data.content);
                setLoading(false);
            } else {
                message.error(res.message);
            }
        }
    }
    const saveContent = useMemo(function () {
        return async function (content: string) {
            if (app_id && item) {
                const res = await apis.save_doc({ app_id, item_id: item.id, parent_id: item.parentId, content });
                if (res.success) {
                    message.success("保存成功");
                    setBase(content);
                    setContent(content);
                    if (res.data.detail && onUpdateTree) {
                        onUpdateTree(res.data.detail);
                    }
                } else {
                    message.error(res.message);
                }
            }
        }
    }, [app_id, item])
    

    useEffect(() => {
        loadContent()
    }, [app_id, item]);


    const editorRef = useRef<HTMLDivElement | undefined>();
    const [editor, setEditor] = useState<EditorView | undefined>();

    useEffect(() => {
        setText(editor, content)
    }, [content, editor]);
    useEffect(function () {
        if (saving) {
            if (editor) {
                saveContent(getText(editor))
                .then(() => setSaving(false))
            } else {
                setSaving(false)
            }
        }
    }, [saving])

    useEffect(() => {
        if (editorRef.current && !editor) {
            const view = new EditorView({
                doc: content,
                parent: editorRef.current,
                extensions: [
                    basicSetup,
                    markdown({ codeLanguages: languages }),
                    history(), // 添加 history 扩展
                    EditorView.domEventHandlers({
                        paste: (e, view) => {
                            const item = e.clipboardData?.items[0]
                            if (item && item.kind === "file") {
                                const type = item.type.startsWith('image/') ? 'image' : 'file';
                                const file = item.getAsFile()
                                uploadFile(view, file, type)
                            }
                        },
                        keydown: (e, view) => {
                            if (e.key === "s" && (e.metaKey || e.ctrlKey)) {
                                e.preventDefault();
                                setSaving(true)
                            }
                        }
                    })
                ],
                dispatch: (tr) => {
                    const newState = view.state.update(tr);
                    view.update([newState]);
                    setContent(getText(view));
                }
            })
            setEditor(view);
        }
        return () => {
            if (editor) {
                editor.destroy();
            }
        };
    }, [editorRef.current]);

    useEffect(() => {
        if (editor) {
            editor.contentDOM.style.minHeight = fullScreen ? "calc(100vh - 48px)" : "calc(100vh - 108px)";
        }
    }, [fullScreen, editor]);


    const uploadFile = async (editor: EditorView, file: File, type: "image" | "file" = "image") => {
        const res = await api_upload(file, app_id)
        if (!res.success) {
            message.error(res.message)
            return
        }
        switch (type) {
            case "image":
                insertText(editor!, `\n![${file.name}](${res.data.url})`)
                break;
            case "file":
                insertText(editor!, `\n[${file.name}](${res.data.url})`)
                break;
        }
    }

    return (
        <Spin spinning={loading}>
            <div className={`${fullScreen ? "w-screen fixed left-0 top-0 right-0 bottom-0 z-10 bg-white" : ""}`}>
                <Splitter className={fullScreen ? "h-screen" : "h-[calc(100vh-64px)]"}>
                    <Splitter.Panel defaultSize="50%" min="30%" max="70%">
                        <Row className="bg-gray-100">
                            <Col span={16}>
                                <Tooltip title="上传图片">
                                    <Upload accept=".gif,.jpg,.png," showUploadList={false} beforeUpload={(file) => {
                                        uploadFile(editor, file)
                                        return false
                                    }}>
                                        <Button size="large" type="text">
                                            <FileImageOutlined />
                                        </Button>
                                    </Upload>
                                </Tooltip>
                                <Tooltip title="撤销(Ctrl+Z)">
                                    <Button size="large" type="text" onClick={() => undo(editor)}>
                                        <UndoOutlined />
                                    </Button>
                                </Tooltip>
                                <Tooltip title="重做(Ctrl+Y)">
                                    <Button size="large" type="text" onClick={() => redo(editor)}>
                                        <RedoOutlined />
                                    </Button>
                                </Tooltip>
                                <Tooltip title="上传附件">
                                    <Upload showUploadList={false} beforeUpload={(file) => {
                                        uploadFile(editor, file, "file")
                                        return false
                                    }}>
                                        <Button size="large" type="text">
                                            <FileOutlined />
                                        </Button>
                                    </Upload>
                                </Tooltip>
                                <Tooltip title="Markdown语法参考">
                                    <Button size="large" type="text" onClick={() => Modal.info({
                                        title: "Markdown语法参考",
                                        content: <pre>{MarkdownDoc}</pre>,
                                        okText: "确定"
                                    })}>
                                        <InfoCircleOutlined />
                                    </Button>
                                </Tooltip>
                            </Col>
                            <Col span={8} className="text-right">
                                <Tooltip title="保存(Ctrl+S)">
                                    <Badge dot={base != content} offset={[-12, 12]}>
                                        <Button size="large" type="text" onClick={() => saveContent(content)}>
                                            <SaveOutlined />
                                        </Button>
                                    </Badge>
                                </Tooltip>
                                <Tooltip title={fullScreen ? "退出全屏" : "全屏"}>
                                    <Button size="large" type="text" onClick={() => {
                                        if (!fullScreen) {
                                            document.documentElement.requestFullscreen();
                                        } else {
                                            document.exitFullscreen();
                                        }
                                    }}>
                                        {fullScreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
                                    </Button>
                                </Tooltip>
                            </Col>
                        </Row>
                        <div ref={editorRef} className={`overflow-auto ${
                            fullScreen ? "h-[calc(100vh-40px)]" : "h-[calc(100vh-104px)]"
                        }`}></div>
                    </Splitter.Panel>
                    <Splitter.Panel>
                        <Markdown skipHtml rehypePlugins={[rehypeHighlight, remarkGFM]} className="markdown-body p-4" components={{
                            code: CustomCode,
                            img: CustomImage,
                            a: CustomLink
                        }}>
                            {formatDoc(content).content}
                        </Markdown>
                    </Splitter.Panel>
                </Splitter>
            </div>
        </Spin>
    );
};